package com.hnust.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hnust.entity.Device;
import com.hnust.entity.Position;
import com.hnust.entity.code.BuildCode;
import com.hnust.entity.code.FloorCode;
import com.hnust.entity.code.RegionCode;
import com.hnust.entity.code.RoomCode;
import com.hnust.entity.dto.CodeDto;
import com.hnust.entity.dto.DeviceDto;
import com.hnust.entity.dto.PositionDto;
import com.hnust.entity.dto.TreeNodeDto;
import com.hnust.mapper.PositionMapper;
import com.hnust.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 创建人：zhangRuWang
 * 创建时间：2022/5/5
 * 描述：
 */
@Service
public class PositionServiceImpl extends ServiceImpl<PositionMapper, Position> implements PositionService {

    @Autowired
    private RegionCodeService regionCodeService;
    @Autowired
    private BuildCodeService buildCodeService;
    @Autowired
    private FloorCodeService floorCodeService;
    @Autowired
    private RoomCodeService roomCodeService;
    @Autowired
    private DeviceService deviceService;

    @Override
    public List<PositionDto> positionList() {
        QueryWrapper<Position> queryWrapper=new QueryWrapper<>();
        queryWrapper.orderByAsc("region_code");
        queryWrapper.orderByAsc("build_code");
        queryWrapper.orderByAsc("floor_code");
        queryWrapper.orderByAsc("room_code");
        queryWrapper.orderByDesc("update_time");
        List<Position> positions=this.list(queryWrapper);
        return positions.stream().map((item)->{
            PositionDto positionDto=new PositionDto();
            this.positionToDto(positionDto,item);
            return positionDto;
        }).collect(Collectors.toList());
    }

    /**
     * 将 position 转为 positionDto
     * @param positionDto dto对象
     * @param position dao对象
     */
    public void positionToDto(PositionDto positionDto,Position position){
        BeanUtils.copyProperties(position,positionDto);
        //设置区域
        QueryWrapper<RegionCode> queryWrapper1=new QueryWrapper<>();
        queryWrapper1.eq("code",position.getRegionCode());
        positionDto.setRegionName(
                regionCodeService.getOne(queryWrapper1).getRegionName()
        );
        //设置建筑
        QueryWrapper<BuildCode> queryWrapper2=new QueryWrapper<>();
        queryWrapper2.eq("code",position.getBuildCode());
        positionDto.setBuildName(
                buildCodeService.getOne(queryWrapper2).getBuildName()
        );
        //设置楼层
        QueryWrapper<FloorCode> queryWrapper3=new QueryWrapper<>();
        queryWrapper3.eq("code",position.getFloorCode());
        positionDto.setFloorName(
                floorCodeService.getOne(queryWrapper3).getFloorName()
        );
        //设置房间
        QueryWrapper<RoomCode> queryWrapper4=new QueryWrapper<>();
        queryWrapper4.eq("code",position.getRoomCode());
        positionDto.setRoomName(
                roomCodeService.getOne(queryWrapper4).getRoomName()
        );
    }

    /**
     * 将位置代码转为可以进行搜索的条件范围
     * @param regionCode 区
     * @param buildCode 建筑
     * @param floorCode 楼层
     * @param roomCode 房间
     * @return 位置ids
     */

    public List<String> positionCodeToList(Integer regionCode,Integer buildCode,
                                           Integer floorCode,Integer roomCode){
        List<Position> positions=this.list(new QueryWrapper<Position>()
                .eq(regionCode!=null,"region_code",regionCode)
                .eq(buildCode!=null,"build_code",buildCode)
                .eq(floorCode!=null,"floor_code",floorCode)
                .eq(roomCode!=null,"room_code",roomCode));
        List<String> positionIds=positions.stream().map(Position::getId).collect(Collectors.toList());
        //stream方法是转成流数据，然后通过map遍历列表元素，这里遍历position把它的id全部存到positionsids中
        if(positionIds.size()==0){
            //添加一个不存在的id使得搜索结果不存在
            positionIds.add("0");
        }
        return positionIds;
    }


    @Override
    public List<DeviceDto> positionListDevice(Integer regionCode, Integer buildCode, Integer floorCode, Integer roomCode) {
       List<String> positionIds=this.positionCodeToList(regionCode,buildCode,
               floorCode,roomCode);
       List<Device> devices=deviceService.list(
               new QueryWrapper<Device>().in("position_id",positionIds)
       );
       return devices.stream().map((item)->{
            DeviceDto deviceDto=new DeviceDto();
            deviceService.deviceToDto(deviceDto,item);
            return deviceDto;
       }).collect(Collectors.toList());
    }

    @Override
    public List<TreeNodeDto> positionTreeList() {
        List<PositionDto> ps=this.positionList();
        Set<CodeDto> codeDtoHashSet=new TreeSet<>(Comparator.comparingInt(CodeDto::getCode));
        List<TreeNodeDto> treeNodeDtos=new ArrayList<>();
        //添加region
        for(PositionDto p:ps){
            codeDtoHashSet.add(new CodeDto(p.getRegionCode(),p.getRegionName()));
        }
        for(CodeDto c:codeDtoHashSet){
            treeNodeDtos.add(new TreeNodeDto(c.getCode(),c.getName()));
        }
        //添加build
        for(TreeNodeDto t:treeNodeDtos){
            Set<CodeDto> cs=new TreeSet<>(Comparator.comparingInt(CodeDto::getCode));
            for(PositionDto p:ps){
                if(p.getRegionCode().equals(t.getCode())&&
                        p.getRegionName().equals(t.getLabel())){
                    cs.add(new CodeDto(p.getBuildCode(),p.getBuildName()));
                }
            }
            for(CodeDto c:cs){
                t.getTreeNodeDtos().add(new TreeNodeDto(c.getCode(),c.getName()));
            }
        }
        //添加 floor
        for(TreeNodeDto t1:treeNodeDtos){
            for(TreeNodeDto t2:t1.getTreeNodeDtos()){
                Set<CodeDto> cs=new TreeSet<>(Comparator.comparingInt(CodeDto::getCode));
                for(PositionDto p:ps){
                    if(p.getRegionCode().equals(t1.getCode())
                            &&p.getRegionName().equals(t1.getLabel())
                    &&p.getBuildCode().equals(t2.getCode())
                    &&p.getBuildName().equals(t2.getLabel())){
                        cs.add(new CodeDto(p.getFloorCode(),p.getFloorName()));
                    }
                }
                for(CodeDto c:cs){
                    t2.getTreeNodeDtos().add(new TreeNodeDto(c.getCode(),c.getName()));
                }
            }
        }
        for(TreeNodeDto t1:treeNodeDtos){
            for(TreeNodeDto t2:t1.getTreeNodeDtos()){
                for(TreeNodeDto t3:t2.getTreeNodeDtos()){
                    Set<CodeDto> cs=new TreeSet<>(Comparator.comparingInt(CodeDto::getCode));
                    for(PositionDto p:ps){
                        if(p.getRegionCode().equals(t1.getCode())
                                &&p.getRegionName().equals(t1.getLabel())
                                &&p.getBuildCode().equals(t2.getCode())
                                &&p.getBuildName().equals(t2.getLabel())
                        &&p.getFloorCode().equals(t3.getCode())
                        &&p.getFloorName().equals(t3.getLabel())){
                            cs.add(new CodeDto(p.getRoomCode(),p.getRoomName()));
                        }
                    }
                    for(CodeDto c:cs){
                        TreeNodeDto t=new TreeNodeDto();
                        t.setCode(c.getCode());t.setLabel(c.getName());
                        t3.getTreeNodeDtos().add(t);
                    }
                }
            }
        }
        return treeNodeDtos;
    }
}
